/* Ekeko - Server based resource loader
 * Copyright (C) 2013 Jorge Luis Zapata
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.
 * If not, see <http://www.gnu.org/licenses/>.
 */
#include "Ekeko.h"
#include "ekeko_private.h"
/*============================================================================*
 *                                  Local                                     *
 *============================================================================*/
typedef struct _Ekeko_Image
{
	uint32_t context_id;
	uint32_t id;
} Ekeko_Image;

typedef struct _Ekeko_Image_Load_Data
{
	Ekeko_Context *ctx;
	Ekeko_Image_Loaded_Cb cb;
	const void *user_data;
} Ekeko_Image_Load_Data;

static void _image_free(void *data, void *user_data)
{
	Ekeko_Image *thiz = user_data;
	Ekeko_Msg_Image_Free msg;

	/* send an unref to the server */
	msg.context_id = thiz->context_id;
	msg.id = thiz->id;
	DBG("Freeing image %d at context %d", msg.id, msg.context_id);
	eix_server_message_send(ekeko_server, EKEKO_MSG_IMAGE_FREE, &msg, NULL, NULL, NULL);
	free(thiz);
}

static Enesim_Surface * _image_load(Ekeko_Msg_Image_Load_Reply *r,
		Ekeko_Context *ctx, Eix_Error *err)
{
	Ekeko_Image *thiz;
	Enesim_Surface *s;
	void *data;

	if (err && eix_error_is_set(err))
	{
		ERR("Failed with error code %d and message '%s'", err->code, err->msg);
		return NULL;
	}

	DBG("Image loaded at offset %d with size %dX%d", r->offset, r->w, r->h);
	thiz = calloc(1, sizeof(Ekeko_Image));
	thiz->context_id = ctx->id;
	thiz->id = r->id;

	data = eshm_segment_map_get(ctx->s);
	data = (unsigned char *)data + r->offset;
	s = enesim_surface_new_data_from(ENESIM_FORMAT_ARGB8888, r->w, r->h,
			EINA_FALSE, data, 0, _image_free, thiz);
	return s;
}

static void _image_loaded(void *reply, Eix_Error *err, void *user_data)
{
	Ekeko_Image_Load_Data *ldata = user_data;
	Ekeko_Msg_Image_Load_Reply *r = reply;
	Enesim_Surface *s;

	DBG("Reply received");
	s = _image_load(r, ldata->ctx, err);
	ldata->cb(s, err, (void *)ldata->user_data);
	free(ldata);
}
/*============================================================================*
 *                                 Global                                     *
 *============================================================================*/
/*============================================================================*
 *                                   API                                      *
 *============================================================================*/

EAPI void ekeko_image_load(Ekeko_Context *ctx, const char *file,
		Enesim_Surface **s, Eix_Error *err)
{
	Ekeko_Msg_Image_Load msg;
	Ekeko_Msg_Image_Load_Reply r = { 0 };

	if (!s || *s) return;
	if (!file) return;
	if (!ctx) return;

	msg.context_id = ctx->id;
	msg.file = file;

	eix_server_message_send(ekeko_server, EKEKO_MSG_IMAGE_LOAD, &msg, &r, err, NULL);
	eix_server_sync(ekeko_server);
	*s = _image_load(&r, ctx, err);
}

EAPI void ekeko_image_load_async(Ekeko_Context *ctx, const char *file,
		Ekeko_Image_Loaded_Cb cb, const void *data)
{
	Ekeko_Image_Load_Data *ldata;
	Ekeko_Msg_Image_Load msg;

	if (!cb) return;
	if (!file) return;
	if (!ctx) return;

	msg.context_id = ctx->id;
	msg.file = (char *)file;

	ldata = calloc(1, sizeof(Ekeko_Image_Load_Data));
	ldata->cb = cb;
	ldata->user_data = data;
	ldata->ctx = ctx;

	eix_server_message_send_deferred(ekeko_server, EKEKO_MSG_IMAGE_LOAD, &msg, _image_loaded, ldata);
}
